package com.example.thirdannotation.y2024.config;


import com.example.thirdannotation.filter.MyTypeFilter;
import com.example.thirdannotation.y2024.bean.Color;
import com.example.thirdannotation.y2024.bean.ColorFactoryBean;
import com.example.thirdannotation.y2024.bean.Person;
import com.example.thirdannotation.y2024.condition.LinuxCondition;
import com.example.thirdannotation.y2024.condition.MyImportBeanDefinitionRegistrar;
import com.example.thirdannotation.y2024.condition.MyImportSelector;
import com.example.thirdannotation.y2024.condition.WindowsCondition;
import org.springframework.context.annotation.*;

/**
 * 给容器中注入组件：
 * 1. 包扫描 + 组件注解
 * 2. @Bean(注入第三方包里的类)
 * 3. @Import(快速给容器中导入一个类，该类并不是一个组件)
 *      3.1 直接导入class
 *      3.2 通过 ImportSelector 导入类
 *      3.3 通过 ImportBeanDefinitionRegistrar 导入
 * 4. 使用Spring提供的FactoryBean(工厂Bean)
 *      1. 默认获取的是工厂bean调用getObject创建的对象
 *      2. 要获取工厂bean本身，需要给id前加一个 & : &colorFactoryBean
 */
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) // id 默认是组件的全类名
@Conditional(WindowsCondition.class)
@Configuration
@ComponentScan(value = "com.example.thirdannotation.y2024", excludeFilters = {
//        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}),
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
})
// 多个component是并列关系，取的是并集而非交集，所以排除不掉
//@ComponentScans(value = {
//        @ComponentScan(value = "com.example.thirdannotation.y2024"),
//        @ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}))
//})
public class MyConfig {

    /**
     * 默认是单实例的，可以通过scope改变
     * prototype: 调用的时候才会创建实例
     * singleton：容器启动就会创建实例
     * @Lazy 懒加载：容器启动的时候不记载，第一次获取的时候再创建实例
     *
     * id: person
     * @return Person
     */
    @Scope(value = "prototype")
    @Bean
    public Person person(){
        return new Person("lisi", 18);
    }

    /**
     * @Conditional: 可以定制自己的条件,决定是否加载该类，如果该注解放在类上，表示对类中的所有方法生效
     * @return
     */
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person personBill(){
        return new Person("bill", 66);
    }

    /**
     * 改变idea的默认系统：vm param: -Dos.name = linux
     * @return
     */
    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person personLinus(){
        return new Person("linus", 66);
    }

    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
}
